<template>
    <div :class="props.class">
        <el-dialog v-model="props.visible" :title="props.title" :close-on-click-modal="false" top="5vh"
            :close-on-press-escape="false" :show-close="false">
            <el-form :model="states.value" ref="formRef" :rules="states.rules">
                <el-row v-for="column in states.columnList.filter(column => !column.isHidden)">
                    <el-col :span="18" :offset="4">
                        <el-form-item :label="column.label" :prop="column.prop" :labelWidth="120">
                            <el-input-number v-if="column.controlTypeCode === `ControlType_Number`"
                                :disabled="column.isReadonly" v-model="states.value[column.prop]" />
                            <el-switch v-else-if="column.controlTypeCode === `ControlType_Boolean`"
                                :disabled="column.isReadonly" v-model="states.value[column.prop]" />
                            <el-date-picker v-else-if="column.controlTypeCode === `ControlType_Date`"
                                :disabled="column.isReadonly" format="YYYY-MM-DD hh:mm:ss"
                                value-format="YYYY-MM-DD hh:mm:ss" v-model="states.value[column.prop]" type="date" />
                            <el-date-picker v-else-if="column.controlTypeCode === `ControlType_DateTime`"
                                :disabled="column.isReadonly" format="YYYY-MM-DD hh:mm:ss"
                                value-format="YYYY-MM-DD hh:mm:ss" v-model="states.value[column.prop]"
                                type="datetime" />
                            <el-select
                                v-else-if="column.controlTypeCode === `ControlType_Select` && states.dictionaryFiltered[column.prop]"
                                :disabled="column.isReadonly" v-model="states.value[column.prop]"
                                @change="getBindFieldDictionary(column.prop)">
                                <el-option v-for="item in states.dictionaryFiltered[column.prop]" :key="item.id"
                                    :label="item.text" :value="item.id"></el-option>
                            </el-select>
                            <el-select
                                v-else-if="column.controlTypeCode === `ControlType_MultiSelect` && states.dictionaryFiltered[column.prop]"
                                :disabled="column.isReadonly" v-model="states.value[column.prop]" multiple collapse-tags
                                collapse-tags-tooltip>
                                <el-option v-for="item in states.dictionaryFiltered[column.prop]" :key="item.id"
                                    :label="item.text" :value="item.id"></el-option>
                            </el-select>
                            <el-input v-else v-model="states.value[column.prop]" autocomplete="off"
                                :disabled="column.isReadonly" />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <template #footer>
                <span>
                    <el-button @click="props.onCancel">{{ lang.CANCEL }}</el-button>
                    <el-button type="primary" @click="onConfirm">{{ lang.CONFIRM }}</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>
<script setup>
import { reactive, ref } from 'vue';
import { lang } from "../lang";

const formRef = ref();
const props = defineProps([
    "class",
    "visible",
    "title",
    "onCancel",
    "onConfirm",
]);

const states = reactive({
    value: {},
    columnList: [],
    rules: {},
    bindFields: [],
    dictionary: {},
    dictionaryFiltered: {}
});

const onConfirm = async () => {
    let checked = false;
    try {
        checked = await formRef.value.validate();
    } catch { }

    if (checked) {
        props.onConfirm();
    }
};

const getBindFieldDictionary = (prop) => {
    let effectedFields = states.bindFields.filter(item => item.bindFields.findIndex(field => field.toLowerCase() === prop.toLowerCase()) >= 0);
    effectedFields.forEach(item => {
        if (states.dictionary[item.field]) {
            let bindValues = [];
            item.bindFields.forEach(bindField => {
                bindValues.push(bindField.toUpperCase() + ":" + states.value[bindField.toLowerCase()]);
            });

            states.dictionaryFiltered[item.field] = [...states.dictionary[item.field].filter(item => item.bindFieldId === bindValues.join())];
            if (states.dictionaryFiltered[item.field].findIndex(field => field.id === states.value[item.field]) < 0) {
                states.value[item.field] = undefined;
            }
        }
    });
};

//是否有值
const hasVal = (val) => {
    return val !== undefined && val !== null && val !== ""
}

const setValue = (buttonType, value, columnList, dictionary) => {
    formRef.value?.resetFields();
    states.columnList = columnList;
    states.dictionary = dictionary;
    states.dictionaryFiltered = { ...dictionary };
    states.value = {};
    states.bindFields = [];
    columnList.forEach(column => {
        try {
            let tempValue = undefined;
            if (buttonType === "MenuType_EditButton") {
                tempValue = value[column.prop];
            } else if (buttonType === "MenuType_AddButton") {
                tempValue = !hasVal(value[column.prop]) ? column.defaultValue : value[column.prop];
            }

            if (column.controlTypeCode === "ControlType_String") {
                states.value[column.prop] = !hasVal(tempValue) ? undefined : tempValue;
            } else if (column.controlTypeCode === "ControlType_Number") {
                states.value[column.prop] = !hasVal(tempValue) ? undefined : Number(tempValue);
            } else if (column.controlTypeCode === "ControlType_Boolean") {
                states.value[column.prop] = !hasVal(tempValue) ? undefined : tempValue === "1";
            } else if (column.controlTypeCode === "ControlType_Date") {
                states.value[column.prop] = !hasVal(tempValue) ? undefined : tempValue;
            } else if (column.controlTypeCode === "ControlType_DateTime") {
                states.value[column.prop] = !hasVal(tempValue) ? undefined : tempValue;
            } else if (column.controlTypeCode === "ControlType_Select") {
                states.value[column.prop] = !hasVal(tempValue) ? undefined : tempValue;

                if (hasVal(column.bindField)) {
                    let fieldsList = column.bindField.trim().split(",");
                    states.bindFields.push({ field: column.prop, bindFields: fieldsList });
                }
            } else if (column.controlTypeCode === "ControlType_MultiSelect") {
                states.value[column.prop] = !hasVal(tempValue) ? undefined : tempValue.split(",");

                if (hasVal(column.bindField)) {
                    let fieldsList = column.bindField.trim().split(",");
                    states.bindFields.push({ field: column.prop, bindFields: fieldsList });
                }
            }

            if (column.rules.length > 0) {
                states.rules[column.prop] = column.rules.map(rule => {
                    if (rule.regExp === "required")
                        return { required: true, message: rule.message };
                    else if (rule.regExp.indexOf("Max:") >= 0)
                        return { type: `${column.controlTypeCode === "ControlType_Number" ? "number" : "string"}`, max: Number(rule.regExp.replace("Max:", "")), message: rule.message };
                    else if (rule.regExp.indexOf("Min:") >= 0)
                        return { type: `${column.controlTypeCode === "ControlType_Number" ? "number" : "string"}`, min: Number(rule.regExp.replace("Min:", "")), message: rule.message };
                    else if (rule.regExp.indexOf("Len:") >= 0)
                        return { type: "string", len: Number(rule.regExp.replace("Len:", "")), message: rule.message };
                    else
                        return { pattern: rule.regExp, message: rule.message };
                });
            }
        } catch (error) {
            console.log(error);
        }
    });

    columnList.forEach(column => getBindFieldDictionary(column.prop));
};

const getValue = () => {
    let value = {};
    states.columnList.forEach(column => {
        if (column.controlTypeCode === "ControlType_String") {
            value[column.prop] = !hasVal(states.value[column.prop]) ? "" : states.value[column.prop];
        } else if (column.controlTypeCode === "ControlType_Number") {
            value[column.prop] = !hasVal(states.value[column.prop]) ? "" : states.value[column.prop].toString();
        } else if (column.controlTypeCode === "ControlType_Boolean") {
            value[column.prop] = !hasVal(states.value[column.prop]) ? "0" : states.value[column.prop] ? "1" : "0";
        } else if (column.controlTypeCode === "ControlType_Date") {
            value[column.prop] = !hasVal(states.value[column.prop]) ? "" : "DateTime:" + states.value[column.prop];
        } else if (column.controlTypeCode === "ControlType_DateTime") {
            value[column.prop] = !hasVal(states.value[column.prop]) ? "" : "DateTime:" + states.value[column.prop];
        } else if (column.controlTypeCode === "ControlType_Select") {
            value[column.prop] = !hasVal(states.value[column.prop]) ? "" : states.value[column.prop];
        } else if (column.controlTypeCode === "ControlType_MultiSelect") {
            value[column.prop] = !hasVal(states.value[column.prop]) ? "" : states.value[column.prop].join(",");
        }
    });

    return value;
};

defineExpose({
    setValue,
    getValue
});

</script>
<style scoped lang="less">

</style>